2 cap[i][j] = Capacidad de la arista (i, j).
3 prev[i] = Predecesor del nodo i en un camino de aumentación.
5 int cap
[MAXN
+1][MAXN
+1], prev
[MAXN
+1];
7 vector
<int> g
[MAXN
+1]; //Vecinos de cada nodo.
8 inline void link(int u
, int v
, int c
){ cap
[u
][v
] = c
; g
[u
].push_back(v
), g
[v
].push_back(u
); }
10 Notar que link crea las aristas (u, v) && (v, u) en el grafo g. Esto es necesario
11 porque el algoritmo de Edmonds-Karp necesita mirar el "back-edge" (j, i) que se crea
12 al bombear flujo a través de (i, j). Sin embargo, no modifica cap[v][u], porque se
13 asume que el grafo es dirigido. Si es no-dirigido, hacer cap[u][v] = cap[v][u] = c.
20 Mantener la red residual, donde residual[i][j] = cuánto flujo extra puedo inyectar
21 a través de la arista (i, j).
23 Si empujo k unidades de i a j, entonces residual[i][j] -= k y residual[j][i] += k
24 (Puedo "desempujar" las k unidades de j a i).
26 Se puede modificar para que no utilice extra memoria en la tabla residual, sino
27 que modifique directamente la tabla cap.
30 int residual
[MAXN
+1][MAXN
+1];
31 int fordFulkerson(int n
, int s
, int t
){
32 memcpy(residual
, cap
, sizeof cap
);
36 fill(prev
, prev
+n
, -1);
39 while (q
.size() && prev
[t
] == -1){
42 vector
<int> &out
= g
[u
];
43 for (int k
= 0, m
= out
.size(); k
<m
; ++k
){
45 if (v
!= s
&& prev
[v
] == -1 && residual
[u
][v
] > 0)
46 prev
[v
] = u
, q
.push(v
);
50 if (prev
[t
] == -1) break;
52 int bottleneck
= INT_MAX
;
53 for (int v
= t
, u
= prev
[v
]; u
!= -1; v
= u
, u
= prev
[v
]){
54 bottleneck
= min(bottleneck
, residual
[u
][v
]);
56 for (int v
= t
, u
= prev
[v
]; u
!= -1; v
= u
, u
= prev
[v
]){
57 residual
[u
][v
] -= bottleneck
;
58 residual
[v
][u
] += bottleneck
;
70 Mantener la red de flujos, donde flow[i][j] = Flujo que, err, fluye
71 de i a j. Notar que flow[i][j] puede ser negativo. Si esto pasa,
72 es lo equivalente a decir que i "absorve" flujo de j, o lo que es
73 lo mismo, que hay flujo positivo de j a i.
75 En cualquier momento se cumple la propiedad de skew symmetry, es decir,
76 flow[i][j] = -flow[j][i]. El flujo neto de i a j es entonces flow[i][j].
80 int flow
[MAXN
+1][MAXN
+1];
81 int fordFulkerson(int n
, int s
, int t
){
82 //memset(flow, 0, sizeof flow);
83 for (int i
=0; i
<n
; ++i
) fill(flow
[i
], flow
[i
]+n
, 0);
86 fill(prev
, prev
+n
, -1);
89 while (q
.size() && prev
[t
] == -1){
92 vector
<int> &out
= g
[u
];
93 for (int k
= 0, m
= out
.size(); k
<m
; ++k
){
95 if (v
!= s
&& prev
[v
] == -1 && cap
[u
][v
] > flow
[u
][v
])
96 prev
[v
] = u
, q
.push(v
);
100 if (prev
[t
] == -1) break;
102 int bottleneck
= INT_MAX
;
103 for (int v
= t
, u
= prev
[v
]; u
!= -1; v
= u
, u
= prev
[v
]){
104 bottleneck
= min(bottleneck
, cap
[u
][v
] - flow
[u
][v
]);
106 for (int v
= t
, u
= prev
[v
]; u
!= -1; v
= u
, u
= prev
[v
]){
107 flow
[u
][v
] += bottleneck
;
108 flow
[v
][u
] = -flow
[u
][v
];